package com.kexilo.exception.service;

import com.kexilo.exception.domain.ExceptionRecord;
import com.kexilo.exception.properties.ExceptionProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 异常处理服务默认实现
 * 支持数据库、异步、去重、通知等企业级功能
 * 
 * @author Kexilo
 */
public class ExceptionServiceImpl implements ExceptionService {
    
    private static final Logger log = LoggerFactory.getLogger(ExceptionServiceImpl.class);
    
    private final ExceptionProperties properties;
    private final JdbcTemplate jdbcTemplate;
    
    // 异常去重缓存（生产环境建议使用Redis）
    private final Map<String, Long> deduplicationCache = new ConcurrentHashMap<>();
    
    // 通知频率限制缓存
    private final Map<String, Long> notificationRateLimit = new ConcurrentHashMap<>();
    
    // 异常处理器和过滤器
    private final List<ExceptionHandler> handlers = new ArrayList<>();
    private final List<ExceptionFilter> filters = new ArrayList<>();
    
    public ExceptionServiceImpl(ExceptionProperties properties, JdbcTemplate jdbcTemplate) {
        this.properties = properties;
        this.jdbcTemplate = jdbcTemplate;
        log.info("异常处理服务初始化完成，存储策略: {}, 通知策略: {}", 
                properties.getStorageStrategy(), properties.getNotificationStrategy());
    }
    
    @Override
    public boolean recordException(ExceptionRecord exceptionRecord) {
        if (exceptionRecord == null) {
            return false;
        }
        
        try {
            // 1. 异常过滤
            if (!passFilters(exceptionRecord)) {
                log.debug("异常被过滤器拦截: {}", exceptionRecord.getExceptionClass());
                return false;
            }
            
            // 2. 异常去重
            if (properties.isDeduplicationEnabled() && isDuplicateException(exceptionRecord)) {
                log.debug("重复异常忽略: {}", exceptionRecord.getExceptionClass());
                return false;
            }
            
            // 3. 生成异常ID
            if (!StringUtils.hasText(exceptionRecord.getExceptionId())) {
                exceptionRecord.setExceptionId(generateExceptionId());
            }
            
            // 4. 存储异常
            boolean stored = storeException(exceptionRecord);
            
            // 5. 发送通知
            if (stored && shouldSendNotification(exceptionRecord)) {
                sendNotification(exceptionRecord);
            }
            
            // 6. 调用自定义处理器
            invokeHandlers(exceptionRecord);
            
            return stored;
            
        } catch (Exception e) {
            log.error("记录异常失败", e);
            return false;
        }
    }
    
    @Override
    @Async("exceptionTaskExecutor")
    public CompletableFuture<Boolean> recordExceptionAsync(ExceptionRecord exceptionRecord) {
        try {
            boolean result = recordException(exceptionRecord);
            return CompletableFuture.completedFuture(result);
        } catch (Exception e) {
            log.error("异步记录异常失败", e);
            return CompletableFuture.failedFuture(e);
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchRecordExceptions(List<ExceptionRecord> exceptionRecords) {
        if (exceptionRecords == null || exceptionRecords.isEmpty()) {
            return 0;
        }
        
        int successCount = 0;
        try {
            for (ExceptionRecord record : exceptionRecords) {
                if (recordException(record)) {
                    successCount++;
                }
            }
            log.info("批量记录异常完成，总数: {}, 成功: {}", exceptionRecords.size(), successCount);
        } catch (Exception e) {
            log.error("批量记录异常失败", e);
        }
        
        return successCount;
    }
    
    @Override
    public ExceptionRecord getExceptionById(String exceptionId) {
        if (!StringUtils.hasText(exceptionId)) {
            return null;
        }
        
        try {
            String sql = "SELECT * FROM " + properties.getDatabase().getExceptionTable() + 
                        " WHERE exception_id = ?";
            List<ExceptionRecord> results = jdbcTemplate.query(sql, getExceptionRecordRowMapper(), exceptionId);
            return results.isEmpty() ? null : results.get(0);
        } catch (Exception e) {
            log.error("查询异常记录失败: {}", exceptionId, e);
            return null;
        }
    }
    
    @Override
    public List<ExceptionRecord> getExceptionsByTraceId(String traceId) {
        if (!StringUtils.hasText(traceId)) {
            return Collections.emptyList();
        }
        
        try {
            String sql = "SELECT * FROM " + properties.getDatabase().getExceptionTable() + 
                        " WHERE trace_id = ? ORDER BY occur_time DESC";
            return jdbcTemplate.query(sql, getExceptionRecordRowMapper(), traceId);
        } catch (Exception e) {
            log.error("根据链路追踪ID查询异常失败: {}", traceId, e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public List<ExceptionRecord> getExceptionsByType(String exceptionType, int limit) {
        try {
            String sql = "SELECT * FROM " + properties.getDatabase().getExceptionTable() + 
                        " WHERE exception_type = ? ORDER BY occur_time DESC LIMIT ?";
            return jdbcTemplate.query(sql, getExceptionRecordRowMapper(), exceptionType, limit);
        } catch (Exception e) {
            log.error("根据异常类型查询失败: {}", exceptionType, e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public List<ExceptionRecord> getUnresolvedExceptions(int limit) {
        try {
            String sql = "SELECT * FROM " + properties.getDatabase().getExceptionTable() + 
                        " WHERE status IN ('PENDING', 'PROCESSING') ORDER BY occur_time DESC LIMIT ?";
            return jdbcTemplate.query(sql, getExceptionRecordRowMapper(), limit);
        } catch (Exception e) {
            log.error("查询未处理异常失败", e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public List<ExceptionRecord> getHighPriorityExceptions(int limit) {
        try {
            String sql = "SELECT * FROM " + properties.getDatabase().getExceptionTable() + 
                        " WHERE level = 'ERROR' AND exception_type IN ('SYSTEM', 'DATABASE') " +
                        " ORDER BY occur_time DESC LIMIT ?";
            return jdbcTemplate.query(sql, getExceptionRecordRowMapper(), limit);
        } catch (Exception e) {
            log.error("查询高优先级异常失败", e);
            return Collections.emptyList();
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateExceptionStatus(String exceptionId, String status, String remark) {
        try {
            String updateSql = "UPDATE " + properties.getDatabase().getExceptionTable() + 
                              " SET status = ?, remark = ?, update_time = ? WHERE exception_id = ?";
            int result = jdbcTemplate.update(updateSql, status, remark, LocalDateTime.now(), exceptionId);
            return result > 0;
        } catch (Exception e) {
            log.error("更新异常状态失败: {}", exceptionId, e);
            return false;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteException(String exceptionId) {
        try {
            String deleteSql = "DELETE FROM " + properties.getDatabase().getExceptionTable() + 
                              " WHERE exception_id = ?";
            int result = jdbcTemplate.update(deleteSql, exceptionId);
            return result > 0;
        } catch (Exception e) {
            log.error("删除异常记录失败: {}", exceptionId, e);
            return false;
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cleanupExpiredExceptions(int daysBeforeNow) {
        try {
            LocalDateTime cutoffTime = LocalDateTime.now().minusDays(daysBeforeNow);
            String deleteSql = "DELETE FROM " + properties.getDatabase().getExceptionTable() + 
                              " WHERE create_time < ?";
            int deleted = jdbcTemplate.update(deleteSql, cutoffTime);
            log.info("清理过期异常记录完成，删除数量: {}", deleted);
            return deleted;
        } catch (Exception e) {
            log.error("清理过期异常记录失败", e);
            return 0;
        }
    }
    
    @Override
    public boolean sendNotification(ExceptionRecord exceptionRecord) {
        if (!shouldSendNotification(exceptionRecord)) {
            return false;
        }
        
        try {
            boolean result = false;
            ExceptionProperties.NotificationStrategy strategy = properties.getNotificationStrategy();
            
            switch (strategy) {
                case EMAIL:
                    result = sendEmailNotification(exceptionRecord, properties.getNotification().getEmailRecipients());
                    break;
                case SMS:
                    result = sendSmsNotification(exceptionRecord, properties.getNotification().getSmsRecipients());
                    break;
                case DINGTALK:
                    result = sendDingTalkNotification(exceptionRecord, properties.getNotification().getDingTalkWebhookUrl());
                    break;
                case WEBHOOK:
                    result = sendWebhookNotification(exceptionRecord, properties.getNotification().getWebhookUrl());
                    break;
                case ALL:
                    // 发送所有类型的通知
                    sendEmailNotification(exceptionRecord, properties.getNotification().getEmailRecipients());
                    sendSmsNotification(exceptionRecord, properties.getNotification().getSmsRecipients());
                    sendDingTalkNotification(exceptionRecord, properties.getNotification().getDingTalkWebhookUrl());
                    result = true;
                    break;
                default:
                    log.debug("通知策略为NONE，跳过通知发送");
                    return false;
            }
            
            if (result) {
                // 更新通知频率限制
                String key = "notification:" + exceptionRecord.getExceptionType();
                notificationRateLimit.put(key, System.currentTimeMillis());
            }
            
            return result;
            
        } catch (Exception e) {
            log.error("发送异常通知失败", e);
            return false;
        }
    }
    
    @Override
    public boolean sendEmailNotification(ExceptionRecord exceptionRecord, List<String> recipients) {
        // 简化实现，生产环境需要集成邮件服务
        log.info("发送邮件通知 - 异常: {}, 收件人: {}", exceptionRecord.getExceptionClass(), recipients);
        return true;
    }
    
    @Override
    public boolean sendSmsNotification(ExceptionRecord exceptionRecord, List<String> phoneNumbers) {
        // 简化实现，生产环境需要集成短信服务
        log.info("发送短信通知 - 异常: {}, 手机号: {}", exceptionRecord.getExceptionClass(), phoneNumbers);
        return true;
    }
    
    @Override
    public boolean sendDingTalkNotification(ExceptionRecord exceptionRecord, String webhookUrl) {
        // 简化实现，生产环境需要调用钉钉API
        log.info("发送钉钉通知 - 异常: {}, WebhookURL: {}", exceptionRecord.getExceptionClass(), webhookUrl);
        return true;
    }
    
    @Override
    public boolean addToDeadLetterQueue(ExceptionRecord exceptionRecord) {
        // 简化实现，生产环境需要使用Redis或消息队列
        log.warn("异常添加到死信队列: {}", exceptionRecord.getExceptionId());
        return true;
    }
    
    @Override
    public List<ExceptionRecord> getFromDeadLetterQueue(int limit) {
        // 简化实现
        return Collections.emptyList();
    }
    
    @Override
    public boolean retryDeadLetterException(String exceptionId) {
        // 简化实现
        log.info("重试死信队列异常: {}", exceptionId);
        return true;
    }
    
    @Override
    public Map<String, Object> getExceptionStatistics() {
        Map<String, Object> stats = new HashMap<>();
        
        try {
            // 总异常数
            String countSql = "SELECT COUNT(*) FROM " + properties.getDatabase().getExceptionTable();
            Integer totalCount = jdbcTemplate.queryForObject(countSql, Integer.class);
            stats.put("totalCount", totalCount);
            
            // 今日异常数
            String todaySql = "SELECT COUNT(*) FROM " + properties.getDatabase().getExceptionTable() + 
                             " WHERE DATE(create_time) = CURDATE()";
            Integer todayCount = jdbcTemplate.queryForObject(todaySql, Integer.class);
            stats.put("todayCount", todayCount);
            
            // 异常类型分布
            String typeSql = "SELECT exception_type, COUNT(*) as count FROM " + 
                           properties.getDatabase().getExceptionTable() + 
                           " GROUP BY exception_type ORDER BY count DESC LIMIT 10";
            List<Map<String, Object>> typeStats = jdbcTemplate.queryForList(typeSql);
            stats.put("typeDistribution", typeStats);
            
            // 处理状态分布
            String statusSql = "SELECT status, COUNT(*) as count FROM " + 
                             properties.getDatabase().getExceptionTable() + 
                             " GROUP BY status";
            List<Map<String, Object>> statusStats = jdbcTemplate.queryForList(statusSql);
            stats.put("statusDistribution", statusStats);
            
        } catch (Exception e) {
            log.error("获取异常统计失败", e);
            stats.put("error", e.getMessage());
        }
        
        return stats;
    }
    
    @Override
    public Map<String, Object> getExceptionTrends(int days) {
        Map<String, Object> trends = new HashMap<>();
        
        try {
            String trendSql = "SELECT DATE(create_time) as date, COUNT(*) as count FROM " + 
                            properties.getDatabase().getExceptionTable() + 
                            " WHERE create_time >= DATE_SUB(CURDATE(), INTERVAL ? DAY) " +
                            " GROUP BY DATE(create_time) ORDER BY date";
            List<Map<String, Object>> trendData = jdbcTemplate.queryForList(trendSql, days);
            trends.put("dailyTrends", trendData);
            
        } catch (Exception e) {
            log.error("获取异常趋势失败", e);
            trends.put("error", e.getMessage());
        }
        
        return trends;
    }
    
    @Override
    public List<Map<String, Object>> getExceptionRankings(String type, int limit) {
        try {
            String column = "exception_type";
            if ("class".equals(type)) {
                column = "exception_class";
            } else if ("module".equals(type)) {
                column = "business_module";
            }
            
            String rankSql = "SELECT " + column + " as name, COUNT(*) as count FROM " + 
                           properties.getDatabase().getExceptionTable() + 
                           " WHERE " + column + " IS NOT NULL " +
                           " GROUP BY " + column + " ORDER BY count DESC LIMIT ?";
            return jdbcTemplate.queryForList(rankSql, limit);
            
        } catch (Exception e) {
            log.error("获取异常排行失败: {}", type, e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public String exportExceptions(String startTime, String endTime, String format) {
        // 简化实现，生产环境需要实现具体的导出逻辑
        log.info("导出异常记录: {} - {}, 格式: {}", startTime, endTime, format);
        return "/tmp/exceptions_" + System.currentTimeMillis() + "." + format.toLowerCase();
    }
    
    @Override
    public boolean shouldSendNotification(ExceptionRecord exceptionRecord) {
        // 1. 检查通知级别
        String notificationLevel = properties.getNotification().getNotificationLevel();
        if (!"ERROR".equals(exceptionRecord.getLevel()) && "ERROR".equals(notificationLevel)) {
            return false;
        }
        
        // 2. 检查通知频率限制
        String key = "notification:" + exceptionRecord.getExceptionType();
        Long lastNotifyTime = notificationRateLimit.get(key);
        if (lastNotifyTime != null) {
            long rateLimitMillis = properties.getNotification().getRateLimitMinutes() * 60 * 1000L;
            if (System.currentTimeMillis() - lastNotifyTime < rateLimitMillis) {
                return false;
            }
        }
        
        return true;
    }
    
    @Override
    public boolean isDuplicateException(ExceptionRecord exceptionRecord) {
        if (!properties.isDeduplicationEnabled()) {
            return false;
        }
        
        // 生成去重键
        String deduplicationKey = generateDeduplicationKey(exceptionRecord);
        Long lastOccurTime = deduplicationCache.get(deduplicationKey);
        
        long windowMillis = properties.getDeduplicationWindow().toMillis();
        long currentTime = System.currentTimeMillis();
        
        if (lastOccurTime != null && (currentTime - lastOccurTime) < windowMillis) {
            return true; // 是重复异常
        }
        
        // 更新缓存
        deduplicationCache.put(deduplicationKey, currentTime);
        
        // 清理过期缓存
        cleanupExpiredDeduplicationCache(currentTime, windowMillis);
        
        return false;
    }
    
    @Override
    public double calculateSimilarity(ExceptionRecord record1, ExceptionRecord record2) {
        // 简化的相似度计算
        double score = 0.0;
        
        if (Objects.equals(record1.getExceptionClass(), record2.getExceptionClass())) {
            score += 0.4;
        }
        if (Objects.equals(record1.getExceptionType(), record2.getExceptionType())) {
            score += 0.3;
        }
        if (Objects.equals(record1.getBusinessModule(), record2.getBusinessModule())) {
            score += 0.2;
        }
        if (record1.getExceptionMessage() != null && record2.getExceptionMessage() != null &&
            record1.getExceptionMessage().contains(record2.getExceptionMessage().substring(0, 
            Math.min(20, record2.getExceptionMessage().length())))) {
            score += 0.1;
        }
        
        return score;
    }
    
    @Override
    public List<String> recommendSolutions(ExceptionRecord exceptionRecord) {
        List<String> solutions = new ArrayList<>();
        
        String exceptionClass = exceptionRecord.getExceptionClass();
        if ("NullPointerException".equals(exceptionClass)) {
            solutions.add("检查变量是否为null");
            solutions.add("使用Optional类处理可能为null的值");
            solutions.add("添加null值校验");
        } else if ("SQLException".equals(exceptionClass)) {
            solutions.add("检查数据库连接");
            solutions.add("验证SQL语句语法");
            solutions.add("检查数据库权限");
        } else if ("TimeoutException".equals(exceptionClass)) {
            solutions.add("增加超时时间设置");
            solutions.add("检查网络连接");
            solutions.add("优化查询性能");
        } else {
            solutions.add("查看完整异常堆栈");
            solutions.add("检查相关配置");
            solutions.add("联系技术支持");
        }
        
        return solutions;
    }
    
    @Override
    public Map<String, Object> analyzeExceptionPatterns(int period) {
        Map<String, Object> analysis = new HashMap<>();
        
        try {
            // 时间段内异常分析
            LocalDateTime startTime = LocalDateTime.now().minusDays(period);
            String patternSql = "SELECT exception_class, COUNT(*) as count, " +
                              "AVG(HOUR(occur_time)) as avg_hour FROM " +
                              properties.getDatabase().getExceptionTable() + 
                              " WHERE occur_time >= ? GROUP BY exception_class " +
                              " HAVING count > 5 ORDER BY count DESC";
            
            List<Map<String, Object>> patterns = jdbcTemplate.queryForList(patternSql, startTime);
            analysis.put("frequentExceptions", patterns);
            
            // 时间分布分析
            String hourSql = "SELECT HOUR(occur_time) as hour, COUNT(*) as count FROM " +
                           properties.getDatabase().getExceptionTable() + 
                           " WHERE occur_time >= ? GROUP BY HOUR(occur_time) ORDER BY hour";
            List<Map<String, Object>> hourDistribution = jdbcTemplate.queryForList(hourSql, startTime);
            analysis.put("hourlyDistribution", hourDistribution);
            
        } catch (Exception e) {
            log.error("异常模式分析失败", e);
            analysis.put("error", e.getMessage());
        }
        
        return analysis;
    }
    
    @Override
    public boolean isAvailable() {
        try {
            if (jdbcTemplate != null) {
                jdbcTemplate.queryForObject("SELECT 1", Integer.class);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.warn("异常处理服务不可用: {}", e.getMessage());
            return false;
        }
    }
    
    @Override
    public Map<String, Object> getHealthStatus() {
        Map<String, Object> health = new HashMap<>();
        
        health.put("enabled", properties.isEnabled());
        health.put("storageStrategy", properties.getStorageStrategy());
        health.put("notificationStrategy", properties.getNotificationStrategy());
        health.put("processingMode", properties.getProcessingMode());
        health.put("available", isAvailable());
        health.put("deduplicationCacheSize", deduplicationCache.size());
        health.put("notificationRateLimitCacheSize", notificationRateLimit.size());
        health.put("handlersCount", handlers.size());
        health.put("filtersCount", filters.size());
        
        return health;
    }
    
    @Override
    public void registerExceptionHandler(ExceptionHandler handler) {
        if (handler != null) {
            handlers.add(handler);
            log.info("注册异常处理器: {}", handler.getClass().getSimpleName());
        }
    }
    
    @Override
    public void registerExceptionFilter(ExceptionFilter filter) {
        if (filter != null) {
            filters.add(filter);
            log.info("注册异常过滤器: {}", filter.getClass().getSimpleName());
        }
    }
    
    /**
     * 存储异常记录
     */
    private boolean storeException(ExceptionRecord exceptionRecord) {
        if (properties.getStorageStrategy() == ExceptionProperties.StorageStrategy.NONE) {
            return true; // 不存储直接返回成功
        }
        
        try {
            switch (properties.getStorageStrategy()) {
                case DATABASE:
                    return storeToDatabase(exceptionRecord);
                case FILE:
                    return storeToFile(exceptionRecord);
                case REDIS:
                    return storeToRedis(exceptionRecord);
                case MIXED:
                    // 混合存储
                    boolean dbResult = storeToDatabase(exceptionRecord);
                    boolean fileResult = storeToFile(exceptionRecord);
                    return dbResult || fileResult;
                default:
                    return false;
            }
        } catch (Exception e) {
            log.error("存储异常记录失败", e);
            return false;
        }
    }
    
    /**
     * 存储到数据库
     */
    private boolean storeToDatabase(ExceptionRecord exceptionRecord) {
        try {
            String insertSql = "INSERT INTO " + properties.getDatabase().getExceptionTable() + 
                              " (exception_id, trace_id, exception_type, exception_class, exception_message, " +
                              "stack_trace, occur_time, user_id, user_name, request_url, request_method, " +
                              "request_params, user_ip, user_agent, browser_type, operating_system, " +
                              "level, status, source, business_module, tags, extra_info, remark, create_time) " +
                              "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
            
            int result = jdbcTemplate.update(insertSql,
                    exceptionRecord.getExceptionId(),
                    exceptionRecord.getTraceId(),
                    exceptionRecord.getExceptionType(),
                    exceptionRecord.getExceptionClass(),
                    exceptionRecord.getExceptionMessage(),
                    exceptionRecord.getStackTrace(),
                    exceptionRecord.getOccurTime(),
                    exceptionRecord.getUserId(),
                    exceptionRecord.getUserName(),
                    exceptionRecord.getRequestUrl(),
                    exceptionRecord.getRequestMethod(),
                    exceptionRecord.getRequestParams(),
                    exceptionRecord.getUserIp(),
                    exceptionRecord.getUserAgent(),
                    exceptionRecord.getBrowserType(),
                    exceptionRecord.getOperatingSystem(),
                    exceptionRecord.getLevel(),
                    exceptionRecord.getStatus(),
                    exceptionRecord.getSource(),
                    exceptionRecord.getBusinessModule(),
                    exceptionRecord.getTags(),
                    exceptionRecord.getExtraInfo(),
                    exceptionRecord.getRemark(),
                    exceptionRecord.getCreateTime()
            );
            
            return result > 0;
        } catch (Exception e) {
            log.error("数据库存储异常记录失败", e);
            return false;
        }
    }
    
    /**
     * 存储到文件
     */
    private boolean storeToFile(ExceptionRecord exceptionRecord) {
        // 简化实现
        log.info("文件存储异常记录: {}", exceptionRecord.getExceptionId());
        return true;
    }
    
    /**
     * 存储到Redis
     */
    private boolean storeToRedis(ExceptionRecord exceptionRecord) {
        // 简化实现
        log.info("Redis存储异常记录: {}", exceptionRecord.getExceptionId());
        return true;
    }
    
    /**
     * 发送Webhook通知
     */
    private boolean sendWebhookNotification(ExceptionRecord exceptionRecord, String webhookUrl) {
        // 简化实现
        log.info("发送Webhook通知 - 异常: {}, URL: {}", exceptionRecord.getExceptionClass(), webhookUrl);
        return true;
    }
    
    /**
     * 生成异常ID
     */
    private String generateExceptionId() {
        return "EX" + System.currentTimeMillis() + "_" + (int)(Math.random() * 1000);
    }
    
    /**
     * 生成去重键
     */
    private String generateDeduplicationKey(ExceptionRecord exceptionRecord) {
        return exceptionRecord.getExceptionClass() + ":" + 
               exceptionRecord.getExceptionType() + ":" +
               (exceptionRecord.getRequestUrl() != null ? exceptionRecord.getRequestUrl() : "");
    }
    
    /**
     * 清理过期的去重缓存
     */
    private void cleanupExpiredDeduplicationCache(long currentTime, long windowMillis) {
        deduplicationCache.entrySet().removeIf(entry -> 
            (currentTime - entry.getValue()) > windowMillis);
    }
    
    /**
     * 检查异常是否通过过滤器
     */
    private boolean passFilters(ExceptionRecord exceptionRecord) {
        // 1. 检查忽略的异常类型
        if (properties.getIgnoreExceptionTypes().contains(exceptionRecord.getExceptionType())) {
            return false;
        }
        
        // 2. 检查忽略的异常类
        if (properties.getIgnoreExceptionClasses().contains(exceptionRecord.getExceptionClass())) {
            return false;
        }
        
        // 3. 检查忽略的URL模式
        String requestUrl = exceptionRecord.getRequestUrl();
        if (requestUrl != null) {
            for (String pattern : properties.getIgnoreUrlPatterns()) {
                if (requestUrl.matches(pattern)) {
                    return false;
                }
            }
        }
        
        // 4. 自定义过滤器
        for (ExceptionFilter filter : filters) {
            if (!filter.filter(exceptionRecord)) {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 调用自定义处理器
     */
    private void invokeHandlers(ExceptionRecord exceptionRecord) {
        for (ExceptionHandler handler : handlers) {
            try {
                handler.handle(exceptionRecord);
            } catch (Exception e) {
                log.error("异常处理器执行失败: {}", handler.getClass().getSimpleName(), e);
            }
        }
    }
    
    /**
     * ExceptionRecord行映射器
     */
    private RowMapper<ExceptionRecord> getExceptionRecordRowMapper() {
        return (rs, rowNum) -> ExceptionRecord.builder()
                .exceptionId(rs.getString("exception_id"))
                .traceId(rs.getString("trace_id"))
                .exceptionType(rs.getString("exception_type"))
                .exceptionClass(rs.getString("exception_class"))
                .exceptionMessage(rs.getString("exception_message"))
                .stackTrace(rs.getString("stack_trace"))
                .occurTime(rs.getTimestamp("occur_time") != null ? 
                          rs.getTimestamp("occur_time").toLocalDateTime() : null)
                .userId(rs.getString("user_id"))
                .userName(rs.getString("user_name"))
                .requestUrl(rs.getString("request_url"))
                .requestMethod(rs.getString("request_method"))
                .requestParams(rs.getString("request_params"))
                .userIp(rs.getString("user_ip"))
                .userAgent(rs.getString("user_agent"))
                .browserType(rs.getString("browser_type"))
                .operatingSystem(rs.getString("operating_system"))
                .level(rs.getString("level"))
                .status(rs.getString("status"))
                .source(rs.getString("source"))
                .businessModule(rs.getString("business_module"))
                .tags(rs.getString("tags"))
                .extraInfo(rs.getString("extra_info"))
                .remark(rs.getString("remark"))
                .createTime(rs.getTimestamp("create_time") != null ? 
                           rs.getTimestamp("create_time").toLocalDateTime() : null)
                .updateTime(rs.getTimestamp("update_time") != null ? 
                           rs.getTimestamp("update_time").toLocalDateTime() : null)
                .build();
    }
}
